package com.lp.module_lib.network.file;

import com.google.gson.JsonParseException;
import com.lp.module_lib.base.BaseContent;
import com.lp.module_lib.network.mvp.ApiException;
import com.lp.module_lib.network.mvp.BaseModel;
import com.lp.module_lib.network.mvp.BaseView;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;

import io.reactivex.observers.DisposableObserver;
import retrofit2.HttpException;

/**
 * 异常处理基类
 * 作者：created by LP_TREAM on 2020/11/25 23:39
 * 邮箱：806875201@qq.com
 */
public abstract class FileObserver<T> extends DisposableObserver<T> {
    protected BaseView mView;

    public static final int PARSE_ERROR = 10008;

    public static final int BAD_NETWORK = 10007;

    public static final int CONNECT_ERROR = 10006;

    public static final int CONNECT_TIMEOUT = 10005;

    public static final int CONNECT_N = 10004;

    //回传标识
    private int mType = 0;
    //true 展示进度条
    private Boolean isShowProgress = false;

    public FileObserver(BaseView view) {
        this.mView = view;
    }

    public FileObserver(BaseView view, int mType) {
        this.mView = view;
        this.mType = mType;
    }

    public FileObserver(BaseView view, Boolean isShowProgress) {
        this.mView = view;
        this.isShowProgress = isShowProgress;
    }

    @Override
    protected void onStart() {
        if (mView != null) mView.showLoading(isShowProgress);
    }

    @Override
    public void onNext(T o) {
        try {
            if (mView != null) mView.hideLoading();

            onSuccessResult(o);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onError(Throwable e) {
        if (mView != null) mView.hideLoading();

        if (e instanceof HttpException) {
            onErrorResult(new BaseModel<>(BAD_NETWORK, "网络超时"));
        } else if (e instanceof ConnectException ||
                e instanceof UnknownHostException) {
            onErrorResult(new BaseModel<>(CONNECT_ERROR, "连接错误"));
        } else if (e instanceof InterruptedIOException) {        //  连接超时
            onErrorResult(new BaseModel<>(CONNECT_TIMEOUT, "连接超时"));
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            onErrorResult(new BaseModel<>(PARSE_ERROR, "数据解析失败"));
        } else if (e instanceof ApiException) {
            /***************************************************************
             * 重点说一下此种情况：此类是接口返回内容不规范，开发中肯定会存在这样类似问题，虽不是前端问题，但前端也可以很好处理此类问题
             * 假如正常情况 返回data为集合
             * code:1
             * msg:获取成功
             * data[ 。。。]
             *
             * 当异常情况下，返回data:{}或者data:""
             * code:0
             * msg:获取失败
             * data:{}或者data:""
             *
             * 这样我们定义好的类型Gson解析会失败，由于类型不统一，并报异常，发生此类情况，在不改动后台代码情况下，
             * 一般通常我们会定义成object类型再手动解析，但这样很是麻烦，所以，可参考此种实现方式
             *
             * 实现原理：拦截gson解析，解析前一步，先解析一遍code,如果是定义正常的，继续向下解析，如果非正常情况，抛异常处理，
             * 并且将接口返回的code,msg一并抛出，异常会在这里拦截！！！！
             **************************************************************/
            ApiException apiException = (ApiException) e;

            onErrorResult(new BaseModel<>(apiException.getErrorCode(), apiException.getMessage()));

        } else {
            if (e != null) {
                onErrorResult(new BaseModel<>(CONNECT_N, e.toString()));
            } else {
                onErrorResult(new BaseModel<>(CONNECT_N, "未知错误"));
            }
        }
    }

    private void onSuccessResult(T o) {
        onSuccess(o);
    }

    private void onErrorResult(BaseModel<T> o) {
        if (mView != null) mView.onErrorState(o, mType);
    }

    @Override
    public void onComplete() {

    }

    public abstract void onSuccess(T o);

}
